%%%-------------------------------------------------------------------
%%% @author Viktor Green <viktor@localhost>
%%% @copyright (C) 2011, Viktor Green
%%% @doc
%%% 
%%% @end
%%% Created :  7 Dec 2011 by Viktor Green <viktor@localhost>
%%%-------------------------------------------------------------------
-module(file_handler_tests).

-include_lib("eunit/include/eunit.hrl").

%% FileInfo record @see http://www.erlang.org/doc/man/file.html#read_file_info-1
-include_lib("kernel/include/file.hrl").

file_handler_test_() ->
    {foreach, fun setup/0, fun teardown/1,
     [{with, [Test]} || Test <- [
				 fun open_close_file/1,
				 fun allocate_file/1,
				 fun write_file/1,
				 fun write_existing_file/1,
				 fun read_file/1
				]]}.

setup() ->
    Path = filename:join([get_priv_folder(), "text.txt"]),
    {ok, Pid} = file_handler:start_link(Path),
    {Pid, Path}.

teardown({Pid, File}) ->
    Ref = erlang:monitor(process, Pid),
    file_handler:close(Pid),
    receive
	{'DOWN', Ref, process, Pid, _Reason} -> ok
    end,
    file:delete(File).

get_priv_folder() ->
    {ok, Dir} = file:get_cwd(),
    Parent = filename:dirname(Dir),
    filename:join([Parent, priv]).

open_close_file({_, FilePath}) ->
    {Result, Pid} = file_handler:start_link(FilePath),
    ?assert(ok == Result),
    Ref = erlang:monitor(process, Pid),
    ?assert(closing == gen_server:call(Pid, close)),
    receive
	{'DOWN', Ref, process, Pid, Reason} ->
	    ?assert(normal == Reason)
    end.

allocate_file({Pid, File}) ->
    Size = 1024 * 1024,
    file_handler:allocate(Pid, Size),
    timer:sleep(2000),
%    ?debugVal(wait_for_allocating_to_complete(Pid)),
    {ok, FileInfo} = file:read_file_info(File),
    ?assert(Size == FileInfo#file_info.size),
    Size.

write_file({Pid, File}) ->
    ?assert(ok == file_handler:write(Pid, 0, <<$h, $e, $l, $l, $o>>)),
    timer:sleep(1000),
    {ok, FileInfo} = file:read_file_info(File),
    ?assert(5 == FileInfo#file_info.size),
    ?assert("hello" == read_file_data(File, 0, 5)).

write_existing_file({Pid, File}) ->
    Size = allocate_file({Pid, File}),
    ?assert(ok == file_handler:write(Pid, 108, "hello")),
    timer:sleep(2000),
    {ok, FileInfo} = file:read_file_info(File),
    ?assert(Size == FileInfo#file_info.size),
    ?assert("hello" == read_file_data(File, 108, 5)).

read_file({Pid, File}) ->
    ok = file:write_file(File, "hello!, today we are learning Erlang"),
    ?assert(<<"hello">> == file_handler:read(Pid, 0, 5)),
    ?assert(<<"learning Erlang">> == file_handler:read(Pid, 21, 15)).

read_file_data(File, Position, Length) ->
    {ok, Device} = file:open(File, [read]),
    {ok, Data} = file:pread(Device, Position, Length),
    ok = file:close(Device),
    Data.
